ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;                    -= Subs and Macros =-
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ


;-----------------------------
; VGA registers and misc
;-----------------------------
 Sequencer      EQU     03C4h
 CRTC           EQU     03D4h
 Input1         EQU     03DAh
 Misc_Out       EQU     03C2h 
 Misc_In        EQU     03CCh
 Attrib_Out     EQU     03C0h
 Attrib_In      EQU     03C1h
 Graphic        EQU     03CEh

 Page_Size       =      21600
 X_Res           =      360
 X_Byte          =      360 / 4
 Y_Res           =      240
 Y_Byte          =      240
;-----------------------------



ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;                           *** MACROS ***
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

;-------------------------------------
; Draw one of the icons to the screen
;-------------------------------------
; In:   SI = Icon to draw
;       DI = Where to putt it
;       DS = ES = Screen
;       All 4 planes selected
;       Write mode 1
;
; Out:  Nothing
;
; Regs: CX SI DI
;--------------------------------------
Macro   Draw_Icon
LOCAL   Next_Line        
	mov     cx,Icon_Res

Next_Line:
	movsb                           ; Move one line to visible screen
	movsb                           ; 3 * 4 = 12 (Icon resolution)
	movsb                           ; *
	add     di,X_Byte-(Icon_Res/4)
	loop    Next_Line
EndM    Draw_Icon
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ




SEGMENT Code_Seg        Para    Public          'CODE'          USE16
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

ASSUME  CS:Code_Seg, SS:Stack_Seg





ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Get input from user
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; In:   SI = String
;       CX = Max chars
;
; Out:  Nothing
;
; Regs: AX BX CX DX BP SI
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Proc    Get_Input
	xor     bx,bx                   ; Page number (Only for old BIOS)


; Flush keyboard buffer
@@10:   mov     ah,1                    ; Test for key
	int     16h
	jz      @@15
	xor     ah,ah                   ; Get key
	int     16h
	jmp     @@10

@@15:   mov     bp,cx

; Get input
@@20:   xor     ah,ah                   ; Wait and get key
	int     16h
	or      al,al                   ; Skipp function keys
	jz      @@20
	cmp     al,CR
	je      @@40
	cmp     al,08h                  ; Back space?
	jne     @@30
	cmp     cx,bp                   ; First char?
	je      @@20
	mov     [Byte ds:si-1],0        ; Delete key in buffer
	mov     ah,0Eh                  ; Delete key on screen
	mov     al,8
	int     10h
	mov     al,' '
	int     10h
	mov     al,8
	int     10h
	dec     si
	inc     cx
	jmp     @@20


; A 'normal' key
@@30:   jcxz    @@20
	cmp     al,20                   ; Skipp chars below 20
	jb      @@20
	mov     ah,0Eh                  ; Write key to the screen
	int     10h
	mov     [Byte ds:si],al         ; Put key into buffer
	inc     si
	dec     cx
	jmp     @@20


; Return is pressed
@@40:   mov     [Byte ds:si],0          ; ASCIIZ
	ret
EndP    Get_Input






ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Get one param (In uppercase)
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; In:   CX = Param number
;
; Out:  SI = ASCIIZ string
;
; Regs: AL CX
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Proc    One_Param
	mov     si,Offset Param_Str
	dec     cx                      ; Zero based!
	jcxz    @@99                    ; CX = Zero --> SI = First param!

@@10:   lodsb                           ; Scan for zero terminator
	or      al,al
	jnz     @@10
	loop    @@10                    ; Do it CX times

@@99:   ret
EndP    One_Param



ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Get the parameter string
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; In:   ES = PSP
;
; Out:  BX = Number of parameters
;
; Regs: -
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Proc    Get_Param
	mov     si,080h
	mov     di,Offset Param_Str
	xor     bx,bx                   ; Parameter count
	xor     ch,ch
	mov     ah,1

	mov     cl,[Byte es:si]         ; Get param length
	jcxz    @@99
	call    _UpperCase              ; Convert to uppercase
	inc     si

	xor     ah,ah                   ; Find first char

@@20:   mov     al,[Byte es:si]         ; Get char
	inc     si
	call    _Check                  ; Is it a seperator
	jne     @@30                    ; No, jump
	dec     cx                      ; Finished?
	jz      @@90
	or      ah,ah                   ; Have we added the zero?
	jz      @@20                    ; Yes, skipp it
	xor     ax,ax                   ; No, write it now
	inc     bl                      ; Param count
	inc     cx                      ; Don't DEC twice!
	jmp     @@31

@@30:   mov     ah,1                    ; Set new param flagg
@@31:   mov     [Byte ds:di],al         ; Write copy to string
	inc     di
	loop    @@20                    ; Do all chars in string

	mov     [Byte ds:di],0          ; Write last zero

@@90:   inc     bl                      ; Count last param
@@99:   ret
EndP    Get_Param



; ZF = 1 --> AL = Seperator (Jump Equal)
Proc    _Check
	cmp     al,020h                 ; Space?
	je      @@99
	cmp     al,09h                  ; TAB?

@@99:   ret
EndP    _Check




; Converts a string to uppercase
Proc    _UpperCase
	push    cx si
	inc     si

@@10:   mov     al,[Byte es:si]
	cmp     al,'a'
	jb      @@20
	cmp     al,'z'
	ja      @@20
	sub     al,'a'-'A'
	mov     [Byte es:si],al

@@20:   inc     si
	loop    @@10

@@99:   pop     si cx
	ret
EndP    _UpperCase




; SI = String --> CX = Length
Proc    Str_Length
	push    si
	mov     cx,0FFFFh               ; Max string length

@@10:   lodsb
	or      al,al
	loopnz  @@10

	not     cx
	dec     cx

	pop     si
	ret
EndP    Str_Length





; SI = ASCIIZ string to write
Proc    Str_Write
	call    Str_Length              ; CX = Length
	mov     bx,1                    ; Standar out handle
	mov     dx,si
	mov     ah,040h                 ; Write to file or device
	int     21h

@@99:   ret
EndP    Str_Write


Proc    New_Line
	mov     ah,2
	mov     dl,CR
	int     21h
	mov     dl,LF
	int     21h
	ret
EndP    New_Line





ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Convert ASCII to binary
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; In:   DI = String to convert
;
; Out:  AX = Value
;       CY = 1 --> Error in string
;
; Regs: ALL - BP
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Proc    ASCII_To_Bin
	mov     si,di
@@00:   lodsb                           ; Find end of string
	or      al,al
	jnz     @@00
	dec     si                      ; SI = Last char

	xor     ax,ax
	xor     dh,dh
	mov     bx,10                   ; Base = 10 (Dec)
	mov     cx,1

@@10:   cmp     si,di
	je      @@99
	dec     si
	mov     dl,[Byte ds:si]
	sub     dl,'0'                  ; Convert from ASCII
	cmp     dl,9
	ja      @@90
	push    cx
	xchg    ax,cx
	mul     dx
	add     cx,ax
	pop     ax
	mul     bx
	xchg    ax,cx
	jmp     @@10

@@90:   stc                             ; Error in string
	ret

@@99:   ret                             ; Ok!
EndP    ASCII_To_Bin







ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Open and load file into memory
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; In:   AX = Segment to load into
;       BX = Handle
;
; Out:  CX = Size (Para aligned)
;       CY = 1 --> Error
;
; Regs: -
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Proc    Load_File
	push    ds
	push    ax
	pop     ds                      ; DS = Where to load the file


; Read from file        
	xor     si,si
	mov     cx,0FFF0h               ; Bytes to read
	xor     dx,dx                   ; DS:0

@@10:   mov     ah,03Fh                 ; Read FFF0h bytes
	int     21h
	jc      @@99
	cmp     ax,0FFF0h               ; Finished?
	jne     @@30                    ; Yes, return

	mov     ax,ds                   ; DS = DS + 0FFFh
	add     ax,00FFFh
	mov     ds,ax
	add     si,00FFFh               ; SI = File size
	cmp     si,[Word ds:Free_Mem]   ; Check if file is to big
	jb      @@10

	stc
	jmp     @@99


; Finish reading
@@30:   mov     bl,al
	and     bl,1111b
	shr     ax,4                    ; Size / 16
	or      bl,bl                   ; Para aligned?
	jz      @@35
	inc     ax                      ; One extra para
@@35:   add     si,ax
	mov     cx,si                   ; CX = File size (Para)

@@99:   pop     ds
	ret
EndP    Load_File




ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Save file (And close it)
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; In:   AX = Seg to data
;       BX = Handle
;       BP = Size (Para)
;
; Out:  CY = 1 --> Error
;
; Regs: -
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Proc    Save_File
	push    ds
	push    ax
	pop     ds

; Seek to start of file
	mov     ax,04200h               ; BX = Handle
	xor     cx,cx
	xor     dx,dx
	int     21h
	jc      @@99


; Write to file
	xor     dx,dx                   ; DS:DX = Data to write
	mov     si,00FFFh               ; Optimiaztion :)

@@10:   mov     ah,040h                 ; Write to file (BX = Handle)
	mov     cx,0FFF0h               ; Write 0FFF0h byte
	cmp     bp,si                   ; Last segment?
	ja      @@20                    ; No, jump

	mov     cx,bp                   ; Last seg
	shl     cx,4                    ; CX = Size
	mov     bp,si                   ; BP = Zero next time

@@20:   int     21h
	jc      @@99
	mov     ax,ds                   ; DS:DX = Old + 00FFFh
	add     ax,si
	mov     ds,ax

	sub     bp,si                   ; Countdown size
	jnz     @@10                    ; Repeat until finished

	mov     ah,03Eh                 ; Close file (BX = Handle)
	int     21h
	jc      @@99
	pop     ds
	ret

@@99:   stc
	pop     ds
	ret
EndP    Save_File







;-------------------------------------
; Draw the icons to the screen
;-------------------------------------
; In:   BP = What to draw
;       DI = Where to draw it
;
; Out:  Nothing
;
; Regs: -
;--------------------------------------
Proc    Draw_Screen
	push    di
	
	mov     dx,Sequencer            ; Select all 4 planes
	mov     ax,0F02h
	out     dx,ax
	mov     bl,1                    ; Set write mode 1
	call    Set_W_Mode
	push    es                      ; DS = ES = Screen
	pop     ds

; Calculate where to start drawing in the map
	mov     al,[Byte gs:Pos_V]
	mul     [Byte gs:Map_H]
	add     al,[Byte gs:Pos_H]
	adc     ah,0
	add     bp,ax

; Draw the screen 30 X 19
	xor     bh,bh                   ; BX = BL
	mov     ax,19                   ; 19 lines of icons

Draw_Screen2:
	mov     dx,30                   ; 30 icons on each line

Draw_Line:
	mov     bl,[Byte gs:bp]         ; Get one byte from the map
	and     bl,00011111b            ; Mask out controll bit
	inc     bp                      ; Next icon in map
	add     bl,bl                   ; It's a word table
	mov     si,[Word gs:Icon_Table + bx]    ; Get offset to icon

; Change frames for animation
	cmp     bl,04*2                 ; Special brick wall?
	je      @@11
	cmp     bl,05*2
	je      @@11
	cmp     bl,07*2                 ; Mask out the icons with no
	jb      @@20                    ; animation
	je      @@12                    ; Green wierd stuff?
	cmp     bl,20*2                 ; Home?
	je      @@17
	cmp     bl,15*2
	ja      @@20
	cmp     bl,09*2                 ; Dimond?
	je      @@10
	cmp     bl,12*2                 ; Monster 1?
	je      @@14

; Icons with 2 frames
@@11:   cmp     [Byte gs:Frame1],0
	je      @@20
	add     si,Icon_size/4          ; Frame 2
	jmp     @@20

; The green wierd stuff
@@12:   cmp     [Byte gs:Frame3],2
	jb      @@20
	add     si,Icon_Size/4
	jmp     @@20

; Monster 1
@@14:   cmp     [Byte gs:Frame4],0
	je      @@20
	add     si,Icon_Size/4
	cmp     [Byte gs:Frame4],1
	je      @@20
	add     si,Icon_Size/4
	jmp     @@20

; Our home
@@18:   mov     si,Icon_Offset + ((Icon_Size/4)*2)  ; Else, draw normal wall
	jmp     @@20
@@17:   cmp     [Byte gs:Frame3],1      ; Do animation
	jbe     @@20
	jmp     @@18


; Icons with 3 frames
@@10:   cmp     [Byte gs:Frame2],0
	je      @@20
	add     si,Icon_Size/4          ; Frame 2
	cmp     [Byte gs:Frame2],1
	je      @@20
	add     si,Icon_Size/4          ; Frame 3

@@20:   Draw_Icon

	sub     di,(X_Byte*12)-3        ; DI = Place to draw next icon
	dec     dx
	jnz     Draw_Line

	add     di,(X_Byte*11)          ; DI = Next line
	mov     bl,[Byte gs:Map_H]
	sub     bl,30
	add     bp,bx                   ; BP = Offset to next line
	dec     ax
	jnz     Draw_Screen2


; *** Draw the status line ***
	pop     di
	push    di
	sub     di,X_Byte*12-3*4

	movzx   bx,[Byte gs:Draw_Type]  ; Get active icon
	movzx   dx,[Byte gs:Type_Table+bx]

	xor     bp,bp                   ; 0 -> 11 Icons

@@30:   movzx   bx,[Byte gs:Type_Table+bp]      ; Get icon from table
	cmp     bx,dx                           ; Active?
	jne     @@32

	cmp     [Byte gs:Frame3],1              ; Flash icon
	ja      @@32
	xor     bx,bx

@@32:   add     bx,bx
	mov     si,[Word gs:Icon_Table+bx]      ; Get offset to icon
	Draw_Icon

	sub     di,(X_Byte*12)-6        ; DI = Place to draw next icon
	inc     bp
	cmp     bp,11
	jne     @@30


; *** Draw the mouse currsor ***
	pop     di                      ; DI = Page to write to
	mov     ax,03h                  ; Get mouse position
	int     33h
	push    dx                      ; Save Y


; Calculate X        
	mov     ax,cx
	shl     ax,6
	xor     dx,dx                   ; AX:DX = X cordinate * 64
	mov     bx,114*12
	div     bx                      ; AX = X cordinate (0 - 29)
	mov     bx,3
	mul     bx                      ; AX = X cordinate (0 - 359)
	mov     si,ax


; Calculate Y
	pop     ax
	shl     ax,6
	xor     dx,dx                   ; AX:DX = Y cordinate * 64
	mov     bx,57*12
	div     bx
	mov     bx,12
	mul     bx                      ; AX = Y cordinate (0 - 239)


; Calculate offset
	mov     bx,X_Byte
	mul     bx
	add     ax,si                   ; AX = (Y * X_Byte) + X
	add     di,ax                   ; DI = Offset

	mov     si,[Word gs:Icon_Table+28*2]     ; Get offset to icon
	Draw_Icon


; Clean up        
	mov     ax,Data_Seg             ; Restore DS
	mov     ds,ax
	xor     bl,bl
	call    Set_W_Mode

	ret
EndP    Draw_Screen



;-------------------------------------
; Convert a binary value to ASCII
;-------------------------------------
; In:   EAX = Value to convert
;       DI = String to hold result
;       CX = Digits in string
;       ES = DS
;
; Out:  Nothing
;
; Regs: ALL - BP
;--------------------------------------
Proc    Bin_To_ASCII
	xor     si,si
	mov     ebx,10                  ; Convert to decimal (Base 10)

@@10:   xor     edx,edx                 ; EDX:EAX = EAX
	div     ebx                     ; EAX = Answer, EDX <- Remainder
	or      dl,'0'                  ; Convert digit to ASCII 0 - 9
	push    dx                      ; Save digit
	inc     si                      ; Count digit
	loop    @@10

	mov     cx,si                   ; CX = Digit on stack
@@20:   pop     ax                      ; al <-- Digit
	stosb
	loop    @@20
	ret
EndP    Bin_To_ASCII




;-------------------------------------
; Install interupt handlers
;-------------------------------------
; In:   Nothing
;
; Out:  Nothing
;
; Regs: -
;--------------------------------------
Proc    Setup_Int

; Setup mouse
	xor     ax,ax                   ; Init mouse
	int     33h
	or      ax,ax                   ; No mouse?
	jnz     @@10

	add     sp,2                    ; Write error message
	mov     dx,Offset Mouse_Str
	jmp     Exit_Write

@@10:   mov     ax,0Fh                  ; Set mouse speed
	mov     cx,8+3
	mov     dx,16+6
	int     33h

	mov     ax,0Ch                  ; Setup mouse interupt
	mov     cx,1
	push    cs
	pop     es
	mov     dx,Offset Mouse_Int
	int     33h


; Set timer 0 to normal speed (Some one may have changed it)
	cli
	mov     al,36h
	out     43h,al
	IODELAY
	xor     ax,ax
	out     40h,al
	IODELAY
	mov     al,ah
	out     40h,al

; Install Keyboard Handler
	mov     eax,[Dword fs:09h*4]
	mov     [Dword ds:Int_09h],eax
	mov     [Word fs:09h*4],offset Keyb_Int
	mov     [Word fs:(09h*4)+2],cs

; Install Timer Interupt
	mov     eax,[Dword fs:08h*4]
	mov     [Dword cs:Int_08h],eax
	mov     [Word fs:08h*4],Offset Timer_Int
	mov     [Word fs:(08h*4)+2],cs
	sti
	
	ret
EndP    Setup_Int



;-------------------------------------
; Set Mode X  (360 X 240 , 256 color)
;-------------------------------------
; In:   Nothing
;
; Out:  ES:DI = Screen
;       All 4 planes selected
;
; Regs: Unknown :)
;--------------------------------------
Proc    ModeX
	mov     ax,0093h                ; Use BIOS to set standard mode 13h
	int     10h                     ; And don't clear VGA mem
	
	mov     dx,Sequencer
	mov     ax,0604h                ; Unchain my VGA
	out     dx,ax                   ; *
	mov     ax,0F02h                ; Select all 4 planes
	out     dx,ax                   ; *
	
	mov     ax,0100h                ; Synchronous reset since we're
	out     dx,ax                   ; changing Clocking Mode reg

	mov     dx,Misc_Out             ; 480 scan lines and 28 MHz clock
	mov     al,11100111b            ; *
	out     dx,al                   ; *
	
	mov     dx,Sequencer            ; Reset sequencer
	mov     ax,0300h
	out     dx,ax

	mov     dx,CRTC                 ; Turn of write protect
	mov     al,011h
	out     dx,al
	inc     dx
	in      al,dx
	and     al,01111111b
	out     dx,al
	dec     dx                      ; DX = CRTC

	mov     si,offset VGA_Registers ; Setup CRT registers
	mov     cx,Num_Regs

Setup_Regs:
	lodsw
	out     dx,ax
	loop    Setup_Regs

	mov     ax,0A000h               ; ES:DI = Screen
	mov     es,ax                   ; *
	xor     di,di                   ; *

	xor     eax,eax                 ; Clear all VGA mem
	mov     cx,04000h
	rep     stosd
	ret                             ; DI is now zero
EndP    ModeX



;-------------------------------------
; Do the startup stuff
;-------------------------------------
; In:   Nothing
;
; Out:  Nothing
;
; Regs: -
;--------------------------------------
Proc    Init

; Setup the palette
	mov     cx,33*3
	mov     si,offset Pal
	call    Write_Col


; Move icons to VGA memory for fast accses
	mov     dx,Sequencer
	mov     si,offset Icons
	mov     di,Icon_Offset
	mov     bx,Num_Icons
	
Next_Icon:
	mov     ax,0102h                ; AL = Map mask reg, AH = Plane 1
	mov     bp,di                   ; Save DI

Next_Plane:
	out     dx,ax                   ; Select plane in AH
	mov     cx,(Icon_Size/16)
	rep     movsd                   ; Move one plane of one icon
	mov     di,bp                   ; Restore DI

	shl     ah,1                    ; Next plane
	test    ah,10000b               ; Done all 4 planes?
	jz      Next_Plane              ; No, next plane
	
	add     di,(Icon_Size/4)        ; Next icon
	dec     bx                      ; Repeat all icons
	jnz     Next_Icon               ; *

	ret
EndP    Init



;-------------------------------------
; Things to do before exit
;-------------------------------------
; In:   Nothing
;
; Out:  Nothing
;
; Regs: -
;--------------------------------------
Proc    Exit_Stuff

; Remove mose interupt
	mov     ax,0Ch
	xor     cx,cx
	int     33h

; Unistall interupt handlers
	cli
	mov     eax,[Dword ds:Int_09h]  ; Restore old Keyboard Handler
	mov     [Dword fs:09h*4],eax
	mov     eax,[Dword cs:Int_08h]  ; Restore old timer interupt
	mov     [Dword fs:08h*4],eax

	sti
	ret
EndP    Exit_Stuff



; Set the write mode
; BL = Mode (0-3)
Proc    Set_W_Mode
	mov     dx,Graphic
	mov     al,05h                  ; Select Mode Register
	out     dx,al                   ; *
	IODELAY
	inc     dx                      ; Read the Mode Register
	in      al,dx                   ; *
	IODELAY
	and     al,11111100b            ; Set write mode
	or      al,bl                   ; *
	out     dx,al                   ; *

	ret
EndP    Set_W_Mode





;-------------------------------------
; Loads up to 256*3 collor registers
;-------------------------------------
; In:   CX = Register to load (*3)
;       SI = Values to load (DS:SI)
;
; Out:  Nothing
;
; Regs: AX CX DX SI
;--------------------------------------
Proc    Write_Col
	call    Wait_VR

	mov     dx,03C8h                ; PEL address register
	xor     al,al                   ; Start with first register
	out     dx,al                   ; *
	inc     dx                      ; Select the data register
	rep     outsb

	ret
EndP    Write_Col



;-------------------------------------
; Write the Start Address register
;-------------------------------------
; In:   BX = Start address
;
; Out:  DX = CRTC
;
; Regs: AX DX
;-------------------------------------
Proc    Write_SA
	mov     dx,Input1
@@10:   in      al,dx                   ; Wait for VR
	test    al,1000b                ; *
	jz      @@10                    ; *


; Update palette
	mov     dx,03C8h
	mov     al,33                   ; Set color 33
	out     dx,al
	inc     dx
	mov     si,Offset Pal+(33*3)
	mov     cx,1*3
@@15:   mov     al,[Byte gs:si]
	shr     al,2                    ; 0 - 64
	inc     si
	out     dx,al
	loop    @@15

	
	mov     dx,Input1
@@20:   in      al,dx                   ; Wait for none VR
	test    al,1000b                ; *
	jnz     @@20                    ; *

Write_SA2:
	mov     dx,CRTC
	mov     al,0Ch                  ; Start address high
	mov     ah,bh                   ; AH = Value
	out     dx,ax

	inc     al                      ; Start address low
	mov     ah,bl                   ; AH = Value
	out     dx,ax
	
	ret
EndP    Write_SA



;-------------------------------------
; Wait for the start of VR
;-------------------------------------
; In:   Nothing
;
; Out:  Nothing
;
; Regs: AX DX
;-------------------------------------
Proc    Wait_VR
	mov     dx,Input1
@@10:   in      al,dx                   ; Wait for non VR
	test    al,1000b                ; *
	jnz     @@10                    ; *

@@20:   in      al,dx                   ; Wait for VR
	test    al,1000b                ; *
	jz      @@20                    ; *
	ret
EndP    Wait_VR
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
EndS    Code_Seg



SEGMENT Data_Seg        Para    Public          'DATA'          USE16
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
VGA_Registers   dw      06B00h          ; Horz total
		dw      05901h          ; Horz Displayed
		dw      05A02h          ; Start Horz Blanking
		dw      08E03h          ; End Horz Blanking
		dw      05E04h          ; Start Horz Sync
		dw      08A05h          ; End Horz Sync
		
		dw      00D06h          ; Vertical Total
		dw      03E07h          ; Overflow
		dw      0EA10h          ; V Sync Start
		dw      08C11h          ; V Sync End and protection
		dw      0DF12h          ; Vertical Displayed
		dw      0E715h          ; V Blank Start
		dw      00616h          ; V Blank End

		dw      04109h          ; Cell Height (2 Scan Lines)
		dw      00014h          ; Dword Mode off
		dw      0E317h          ; Byte Mode on
		dw      02D13h          ; Offset register 360 / 8 = 45 (02Dh)
Num_Regs        EQU     17
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
EndS     Data_Seg
